home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Libraries / SAT 2.3b4 / Demo ƒ / HeartQuest demo ƒ / main.p < prev    next >
Text File  |  1995-01-22  |  11KB  |  318 lines

  1. {================================================}
  2. {=============== HeartQuest main unit ================}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { HeartQuest is a very simple game demonstrating how to use the Sprite Animation}
  10. { Toolkit. I originally wrote the game as my present to my wife Eva for Valentine's}
  11. { day 1992. You can still tell that this file once started as the Skel example in the}
  12. { TransSkel package by Paul DuBois and Owen Hartnett. }
  13.  
  14. { This "main" file is rather small, and holds very little game specific code.}
  15. { Its main concern is to initialize the various parts of the game, and to hold the}
  16. { file and edit menu handlers. }
  17.  
  18. program HeartQuest;
  19.  
  20.     uses
  21. {$IFC UNDEFINED THINK_PASCAL}
  22.         Types, Quickdraw, Events, Windows, Resources, 
  23. {$ENDC}
  24.         TransSkel, SAT, GameGlobals, GameWindow, {sound,}
  25.         SoundConst, scores, CenterStuff, Preferences, AppleEvents, ClutFade;
  26.  
  27. {Variables for the main program}
  28.     var
  29.         keys: KeyMap;
  30.         zoomFlag: Boolean;
  31.         ignore: longint;                        {For UnloadScrap error}
  32.         gAppleEventsInitialized: Boolean;    {For initializing Apple Events when necessary}
  33.  
  34. { -------------------------------------------------------------------- }
  35. {                        Menu handling procedures                        }
  36. { -------------------------------------------------------------------- }
  37.  
  38. {    Handle selection of "About…" item from Apple menu}
  39.  
  40.     procedure DoAbout;
  41.         var
  42.             ignore: integer;
  43.     begin
  44.         ignore := DoAlert(43, aboutAlrt, nil);
  45.     end;
  46.  
  47. {    Process selection from File menu.}
  48.  
  49. {    HelpEnemies    Shows a help box. }
  50. {    Quit    Request a halt by calling SkelHalt().  This makes SkelMain}
  51. {            return.}
  52.  
  53.     procedure DoFileMenu (item: integer);
  54.         var
  55.             ignore: integer;
  56.     begin
  57.         case item of
  58.             helpenemies: 
  59.                 ignore := DoAlert(43, helpenemiesAlrt, nil);
  60.             quit: 
  61.                 begin
  62.                     if pauseFlag then
  63.                         DoGameOver;
  64.                     SkelWhoa;
  65.                 end;
  66.             otherwise
  67.                 ;
  68.         end;
  69.     end;
  70.  
  71.     procedure DoEditMenu;
  72.     begin
  73.     end;
  74.  
  75. {    Initialize menus.  Tell TransSkel to process the Apple menu}
  76. {    automatically, and associate the proper procedures with the}
  77. {    File and Edit menus.}
  78.  
  79.     procedure SetUpMenus;
  80.     begin
  81.         SkelApple(MyGetIndString(aboutStrID), @DoAbout); {string 1: About HeartQuest…}
  82.         fileMenu := GetMenu(fileMenuRes);
  83.         editMenu := GetMenu(editMenuRes);
  84.         GameMenu := GetMenu(GameMenuRes);
  85.         highMenu := GetMenu(highMenuRes);
  86.         dummy := SkelMenu(fileMenu, @DoFileMenu, nil, false);
  87.         dummy := SkelMenu(editMenu, @DoEditMenu, nil, false);
  88.         dummy := SkelMenu(GameMenu, @DoGameMenu, nil, false);
  89.         dummy := SkelMenu(highMenu, @DoHighMenu, nil, true);
  90.     end;
  91.  
  92. { Initialize settings resources. These are saved in the game file itself. This is elegant,}
  93. { but a bit "server-hostile". An alternative is to create a preference file in the system}
  94. { folder. The routine determining where preferences should be saved, in Preferences.p,}
  95. { has a parameter that can be set to always save in a preference file, if you prefer that.}
  96.  
  97.     procedure InitSettings;
  98.     begin
  99.         UseResFile(gPrefFile); {set the resfile to the pref file, if any. If none, gPrefFile will be the app itself!}
  100.         features := featHnd(GetResource('Feat', 0));        { Load the settings }
  101.         if features = nil then                                { Settings doesn't exist; create new }
  102.             begin
  103.                 features := featHnd(NewHandle(Sizeof(featRec)));
  104.                 CheckNoMem(Ptr(features));
  105.                 features^^.sound := true;
  106.                 features^^.allowBG := false;
  107.                 features^^.player := MyGetIndString(anonymousStrID); {str 2: Anonymous}
  108.                 features^^.macho := false;
  109.                 AddResource(handle(features), 'Feat', 0, 'Settings');
  110.             end
  111.         else                                                    {Did exist - check the size!}
  112.             if GetHandleSize(Handle(features)) < sizeof(featHnd) then
  113.                 SetHandleSize(Handle(features), sizeof(featHnd));
  114.         UseResFile(gAppFile);
  115.  
  116. { Fix all checkmarks in the menus }
  117.         if features^^.sound then
  118.             begin
  119.                 features^^.sound := false;
  120.                 DoGameMenu(sound);
  121.             end
  122.         else
  123.             begin
  124.                 features^^.sound := true;
  125.                 DoGameMenu(sound);
  126.             end;
  127.         if features^^.macho then
  128.             begin
  129.                 features^^.macho := false;
  130.                 DoGameMenu(macho);
  131.             end
  132.         else
  133.             begin
  134.                 features^^.macho := true;
  135.                 DoGameMenu(macho);
  136.             end;
  137.         if features^^.PlotFast then
  138.             begin
  139.                 features^^.PlotFast := false;
  140.                 DoGameMenu(FastAnimation);
  141.             end
  142.         else
  143.             begin
  144.                 features^^.PlotFast := true;
  145.                 DoGameMenu(FastAnimation);
  146.             end;
  147.         if features^^.allowBG then
  148.             begin
  149.                 features^^.allowBG := false;
  150.                 DoGameMenu(allowBG);
  151.             end
  152.         else
  153.             begin
  154.                 features^^.allowBG := true;
  155.                 DoGameMenu(allowBG);
  156.             end;
  157.     end;
  158.  
  159.  
  160. { ******* MultiFinder and Apple events: ******* }
  161.  
  162. {MultiFinder events - suspend and reume - have been handled by HeartQuest since very early versions,}
  163. {since I want it to hide its window when switched out.}
  164. {AppleEvents are added, mostly because I wanted to learn about it. I learned one thing: Apple Events are}
  165. {tedious. I tried simplifying AppleEvent support by installing my handlers first after getting an Apple}
  166. {Event (getting rid of all checking for its existence - if it sends events to me, it exists) - but the interface}
  167. {files needed are horrible. To speed up compilation, I made a stripped down interface file, HQAE.p.}
  168. {All I really got by supporting Apple Events is that I can quit after getting the 'quit' Apple event.}
  169.  
  170. {Handle the required Apple events:}
  171. {DoOpenApp,DoOpenDoc,DoPrintDoc,DoQuitApp}
  172. {MyGotRequiredParams: From MSG demo my Mark Pilgrim, tells whether we have handled all we have to or not.}
  173.     function MyGotRequiredParams (theAppleEvent: AppleEvent): OSErr;
  174.         var
  175.             returnedType: DescType;
  176.             actualSize: Size;
  177.     begin
  178.         if AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard, returnedType, nil, 0, actualSize) = errAEDescNotFound then
  179.             MyGotRequiredParams := noErr
  180.         else
  181.             MyGotRequiredParams := errAEParamMissed;
  182.     end;
  183.     function DoOpenApp (theAppleEvent, reply: AppleEvent; refCon: Longint): OSErr;
  184.     begin
  185. {What am I supposed to do here?}
  186.         DoOpenApp := MyGotRequiredParams(theAppleEvent);
  187.     end;
  188.     function DoOpenDoc (theAppleEvent, reply: AppleEvent; refCon: Longint): OSErr;
  189.     begin
  190.         DoOpenDoc := errAEEventNotHandled; {We don't open any documents!}
  191.     end;
  192.     function DoPrintDoc (theAppleEvent, reply: AppleEvent; refCon: Longint): OSErr;
  193.     begin
  194.         DoPrintDoc := errAEEventNotHandled; {We don't print any documents!}
  195.     end;
  196.     function DoQuitApp (theAppleEvent, reply: AppleEvent; refCon: Longint): OSErr;
  197.     begin
  198.         SkelWhoa;            {If I'm told to quit, I'll quit.}
  199.         DoQuitApp := MyGotRequiredParams(theAppleEvent);
  200.     end;
  201.  
  202. {Init Apple events}
  203. {Perhaps I'm cheating, but I don't call this until I get the first Apple event.}
  204. {IMHO, that's the simplest way to support them without a lot of boring Gestalt checks.}
  205.     procedure AppleEventInit;
  206.         var
  207.             error: OSerr;
  208.     begin
  209.         if gAppleEventsInitialized then
  210.             exit(AppleEventInit);
  211.         gAppleEventsInitialized := true;
  212.         error := AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, @DoOpenApp, 0, false);
  213.         error := AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, @DoOpenDoc, 0, false);
  214.         error := AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, @DoPrintDoc, 0, false);
  215.         error := AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, @DoQuitApp, 0, false);
  216. {I ignore errors.}
  217.     end;
  218.  
  219.  
  220. {Event processing that TransSkel nowadays HAS support for:}
  221. {MultiFinder events: Hide gameWindow on suspend, so the user can get access to disk icons etc.}
  222. {Apple Events: Handle the required Apple events.}
  223.  
  224.     procedure DoSuspendResume (b: Boolean);
  225.     begin
  226.         if b then
  227. {Resume event: show game window and set the sleep time to something fairly low}
  228.             begin
  229.                 ShowWindow(gSAT.wind.port);
  230.                 SelectWindow(gSAT.wind.port);
  231.                 SkelSetSleep(5);
  232.             end
  233.         else
  234. {Suspend event: Hide the game window and set the sleep time to something high}
  235. {(Not that the sleep time matters when "can background" is false, but I put it in for demonstrating it.)}
  236.             begin
  237.                 HideWindow(gSAT.wind.port);
  238.                 SkelSetSleep(60);
  239.             end;
  240.     end;
  241.  
  242.     function DoEvt (e: eventRecord): boolean;
  243.     begin
  244. {In older versions, we handled Apple events and suspend/resume events here. Since then,}
  245. {I have added support for them in TransSkel.p, so now this is only used for installing our}
  246. {Apple Event handlers upon acceptance of the first Apple Event.}
  247.  
  248. {Old obsolete code: Handle suspend/resume events}
  249. {if e.what = OSevt then}
  250. {begin}
  251. {if BAND(BROTL(e.message, 8), $FF) = SuspendResumeMessage then}
  252. {DoSuspendResume(BAnd(e.message, 1) <> 0);}
  253. {DoEvt := true;}
  254. {end}
  255. {else}
  256.  
  257.         DoEvt := false; {We never actually PROCESS any event here!}
  258.         if e.what = kHighLevelEvent then
  259.             if not gAppleEventsInitialized then {My little "cheat" into compatibility}
  260.                 AppleEventInit;
  261. {if AEProcessAppleEvent(e) <> noErr then}
  262.     end; { DoEvt }
  263.  
  264.  
  265. { -------------------------------------------------------------------- }
  266. {                                    Main                                }
  267. { -------------------------------------------------------------------- }
  268.  
  269. begin
  270.     SkelInit(6, nil);                { initialize }
  271.     SetUpMenus;                { install menu handlers }
  272.  
  273. {Is the user holding down a modifier key? If so, we should use the whole screen.}
  274.     GetKeys(keys);
  275.     zoomFlag := keys[55] or keys[56] or keys[58] or keys[59]; {cmd, shift, alt, ctrl}
  276.  
  277. {Tell SAT that we want it to rescale the PICTs}
  278.     SATConfigure(true, kVPositionSort, kKindCollision, 32);
  279.  
  280. {Send strings from resources to SAT, so the program can be localized.}
  281.     SATSetStrings(MyGetIndString(okStrID), MyGetIndString(yesStrID), MyGetIndString(noStrID), MyGetIndString(quitStrID), MyGetIndString(memerrStrID), MyGetIndString(noscreenStrID), MyGetIndString(satnopictStrID), MyGetIndString(nowindStrID));
  282.  
  283.     fadeTo.red := -1;
  284.     fadeTo.green := $a000;
  285.     fadeTo.blue := $a000;
  286.     FadeScreen(30, true, fadeTo);
  287.  
  288. { Initialize the Sprite Animation Toolkit, set up offscreen buffers and make the window. }
  289.     if zoomFlag then {if cmd, shift, alt, ctrl}
  290.         SATInit(132, 133, 32000, 32000) {Very big - makes SAT cut it down to the main screen.}
  291.     else
  292.         SATInit(132, 133, 512, 322); {Standard size}
  293.  
  294. {Here we can call SATSoundInitChannels if we want more than one channel.}
  295.  
  296. { Init all the different parts of the game. }
  297.     GameWindInit;    { Init the game window }
  298.  
  299.     FadeScreen(30, false, fadeTo);
  300.  
  301.     Loadsounds;        { preload all sound resources }
  302.     InitScores;        { Init the score module, check if a pref file should be created }
  303.     InitSettings;    { Load the settings }
  304.  
  305. { Set the randseed to something that is random enough. }
  306. {$IFC UNDEFINED THINK_PASCAL}
  307.     qd.randSeed := TickCount;
  308. {$ELSEC}
  309.     randSeed := TickCount;
  310. {$ENDC}
  311.  
  312.     SkelEventHook(@DoEvt); { handle MultiFinder-events }
  313.     SkelSetSuspendResume(@DoSuspendResume); {NEW call in my version of TransSkel 2.0}
  314.  
  315.     SkelMain;                { loop 'til Quit selected }
  316.     SkelClobber;                { clean up }
  317.     SATSoundShutUp;            { Terminate sounds }
  318. end.